package com.shouchuang.websocketserver;

import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import org.json.JSONObject;
import org.json.JSONArray;
import android.util.Log;


public class Server extends WebSocketServer {
    private int UserIndex = 0;
    HashMap<Integer,User> userDict = new HashMap<Integer,User>();
    HashMap<WebSocket,Integer> socketDict = new HashMap<WebSocket,Integer>();
    HashMap<Integer,Room> roomDict = new HashMap<Integer,Room>();

    class User {
        public int Id;
        public int room;
        public WebSocket socket;
    }

    class Room {
        public String type;
        public int maxUserCount;
        public List<Integer> userList = new ArrayList<Integer>();
        public boolean isFull(){
            return userList.size() >= maxUserCount;
        }
    }

    public Server(){
        super(new InetSocketAddress(8181));
    }
    
    final String LOGTAG = "WebSocketServer";
    private void logText(String text) {
        Log.d(LOGTAG, text);
    }
 
    @Override
    public void onOpen(WebSocket socket, ClientHandshake handshake) {
        int userId = ++UserIndex;
        logText(userId + " Connected");
        try{
            User user = new User();
            user.Id = userId;
            user.socket = socket;
            userDict.put(userId,user);
            socketDict.put(socket,userId);

            JSONObject jo = new JSONObject();
            jo.put("_","user");
            jo.put("user",userId);
            socket.send(jo.toString());
        }
        catch(Exception ex){
            logText(ex.toString());
        }
    }
 
    @Override
    public void onClose(WebSocket socket, int code, String reason, boolean remote) {
        try {
            int userId = socketDict.get(socket);
            logText(userId + " Disconnected");
            quitRoom(userId);
            userDict.remove(userId);
            socketDict.remove(socket);
        }
        catch(Exception ex){
            logText(ex.toString());
        }
    }
 
    @Override
    public void onMessage(WebSocket socket, String message) {
        //logText("收到消息: "+message);
        try {
            int userId = socketDict.get(socket);
            JSONObject jo = new JSONObject(message);
            switch (jo.getString("_"))
            {
                case "createRoom": {
                        quitRoom(userId);
                        int count = jo.getInt("count");
                        Room room = new Room();
                        room.type = jo.getString("type");
                        room.maxUserCount = count;
                        room.userList.add(userId);
                        roomDict.put(userId,room);
                        userDict.get(userId).room = userId;
                        socket.send(message);
                    }
                    break;
                case "getRoom": {
                        String type = jo.getString("type");
                        JSONArray list = new JSONArray();
                        roomDict.forEach((id,room) -> {
                            if (room.type.equals(type) && !room.isFull())
                                list.put(id);
                        });
                        jo.put("list",list);
                        socket.send(jo.toString());
                    }
                    break;
                case "joinRoom": {
                        int room = jo.getInt("room");
                        if (!roomDict.containsKey(room))
                        {
                            socket.send("{\"error\":\"房间已关闭\"}");
                            break;
                        }
                        if (roomDict.get(room).isFull())
                        {
                            socket.send("{\"error\":\"房间玩家已满\"}");
                            break;
                        }
                        if (room==userId)
                        {
                            socket.send("{\"error\":\"你已经在此房间了\"}");
                            break;
                        }
                        quitRoom(userId);
                        roomDict.get(room).userList.add(userId);
                        userDict.get(userId).room = room;
                        jo.put("user",userId);
                        jo.put("start",roomDict.get(room).isFull() ? 1 : 0);
                        String msg = jo.toString();
                        roomDict.get(room).userList.forEach(p -> {
                            userDict.get(p).socket.send(msg);
                        });
                    }
                    break;
                case "quitRoom": {
                        quitRoom(userId);
                    }
                    break;
                default: {
                        int roomId = userDict.get(userId).room;
                        if (!roomDict.containsKey(roomId))
                            break;
                        Room room = roomDict.get(roomId);
                        room.userList.forEach(p -> {
                            userDict.get(p).socket.send(message);
                        });
                    }
                    break;
            }
        }
        catch (Exception ex) {
            logText(ex.toString());
        }
    }
 
    @Override
    public void onError(WebSocket socket, Exception ex) {
        logText("错误: "+ex.getMessage());
    }
 
    @Override
    public void onStart() {
        logText("服务已启动");
    }

    void quitRoom(int userId) {
        try{
            int roomId = userDict.get(userId).room;
            if (!roomDict.containsKey(roomId))
                return;
            Room room = roomDict.get(roomId);
            if (roomId == userId)
                roomDict.remove(roomId);
            room.userList.remove(userId);
            userDict.get(userId).room = 0;

            JSONObject jo = new JSONObject();
            jo.put("_","quitRoom");
            jo.put("user",userId);
            jo.put("disband",roomId == userId ? 1 : 0);
            String msg = jo.toString();
            room.userList.forEach(p -> {
                if(roomId == userId)
                    userDict.get(p).room = 0;
                userDict.get(p).socket.send(msg);
            });
        }
        catch(Exception ex){
            logText(ex.toString());
        }
    }
}